#pragma once


/// Wrapper class template for handler objects to allow handler memory allocation to be customised
template <typename Handler>
class CustomAllocHandler
{
public:
	/// Construct an instance for the given handler
	CustomAllocHandler(Handler h)
		: _handler(h)
	{
	}

	/// Forwards call to operator() to the encapsulated handler
	template <typename Arg1>
	void operator()(Arg1 arg1)
	{
		_handler(arg1);
	}

	/// Forwards call to operator() to the encapsulated handler
	template <typename Arg1, typename Arg2>
	void operator()(Arg1 arg1, Arg2 arg2)
	{
		_handler(arg1, arg2);
	}

	/// Allocates memory for temporary asio objects using TBB scalable_allocator
	friend void* asio_handler_allocate(std::size_t size, CustomAllocHandler<Handler> * /*thisHandler*/)
	{
		return scalable_malloc(size);
	}

	/// Frees memory for temporary asio objects using TBB scalable_allocator
	friend void asio_handler_deallocate(void *pointer, std::size_t /*size*/, CustomAllocHandler<Handler> * /*thisHandler*/)
	{
		scalable_free(pointer);
	}

private:
	Handler _handler;
};

/// Helper function to wrap a handler object to add custom allocation
template <typename Handler>
inline CustomAllocHandler<Handler> MakeCustomAllocHandler(Handler h)
{
	return CustomAllocHandler<Handler>(h);
}
